/*
 * @(#)Signature.java	1.50 01/12/12
 *
 * 版权所有2002年Sun MicroSystems，Inc. All rights reserved.  Sun专有/机密。使用须遵守许可条款。
 */
 
 
package java.security;

import java.util.*;
import java.io.*;
/**
 * 此Signature类用于提供数字签名算法的功能，例如<tt>具有MD5</tt>或<tt>DSA的</tt>RSA。数字签名用于数字数据的身份验证和完整性保证。
 *
 * </dl> 
 *
 * 与Java Security中其他基于算法的类一样，Signature类有两个主要组件：
 *
 * <dl>
 *
 * <dt><b>Digital Signature API</b> (Application Program Interface)
 *
 * <dd>这是需要数字签名服务的应用程序调用的方法的接口。API由所有公共方法组成。
 *
 * <dt><b>Digital Signature SPI</b> (Service Provider Interface)
 *
 * <dd>这是由提供特定算法的提供商实现的接口。它由名称以<code>引擎</code>为开头的所有方法组成。
 * 每个此类方法都由相应名称的公共API方法调用。例如，<code>engineSign</code>方法由<code>sign</code>方法调用。
 * SPI方法是抽象的;提供商必须提供具体的实现。
 *
 * </dl>
 *
 * <p>与Java Security中的其他基于算法的类一样，Signature提供了与实现无关的算法，
 * 调用者（应用程序代码）由此请求特定的签名算法并传回正确初始化的Signature对象。
 * 如果需要，还可以向特定提供商请求特定算法。请参阅<code>getInstance</code>方法。
 *
 * <p>因此，有两种方法可以请求Signature算法对象：仅指定算法名称，或者同时指定算法名称和包提供程序。<ul>
 *
 * <li>如果只指定了一个算法名称，系统将确定环境中是否有所请求算法的可用实现，如果有多个，是否有首选实现。
 *
 * <li>如果同时指定了算法名称和包提供者，系统将确定所请求的包中是否有算法的实现，如果没有，则抛出异常。
 *
 * </ul>

 * <p>Signature对象可用于生成和验证数字签名。
 *
 * <p>使用Signature对象对数据进行签名或验证签名有三个阶段：<ol>
 *
 * <li>Initialization, with either 
 *
 *     <ul>
 *
 *     <li>a public key, which initializes the signature for
 *     verification (see <a href = "#initVerify">initVerify</a>), or
 *
 *     <li>a private key, which initializes the signature for
 *     signing (see <a href = "#initSign">initSign</a>).
 *
 *     </ul><p>
 *
 * <li>Updating<p>
 *
 * <p>根据初始化类型，这将更新要签名或验证的字节。查看<a href = "#update(byte)">更新</a>方法。<p>
 *
 * <li>Signing or Verifying 
 *
 * <p>a signature on all updated bytes. See <a
 * href = "#sign">sign</a> and <a href = "#verify">verify</a>.
 *
 * </ol>
 *
 * @version 1.44 97/02/03
 * @author Benjamin Renaud 
 */
public abstract class Signature {

    /*  Are we in debugging mode? */
    private static boolean debug = false;

    /* The algorithm for this signature object. */
    private String algorithm;

    /** 
     * 可能的<a href = "#state ">状态</a>值，表示此签名对象尚未初始化。
     */      
    protected final static int UNINITIALIZED = 0;       
       
    /** 
     * 可能的<a href = "#state ">状态</a>值，表示此签名对象已初始化以进行签名。
     */      
    protected final static int SIGN = 2;
       
    /** 
     * Possible <a href = "#state ">state </a> value, signifying that       
     * this signature object has been initialized for verification.
     */      
    protected final static int VERIFY = 3;

    /** 
     * Current state of this signature object.
     */      
    protected int state = UNINITIALIZED;

    /**
     * Creates a Signature object for the specified algorithm.
     *
     * @param 算法的标准字符串名称。有关标准算法名称的信息，
     * 请参阅《<a href= "../guide/security/CryptoSpec.html#AppA">Java加密架构API规范参考》</a>中的附录A。
     */
    protected Signature(String algorithm) {
	this.algorithm = algorithm;
    }

    /**
     * 生成实现指定算法的Signature对象。如果默认提供程序包包含实现该算法的Signature子集，则返回该子集的实例。
     * 如果该算法在默认包中不可用，则会搜索其他包。
     *
     * @param 算法请求的算法的标准名称。
     * 有关标准算法名称的信息，请参阅《<a href= "../guide/security/CryptoSpec.html#AppA">Java加密架构API规范参考》</a>中的附录A。
     *
     * @return the new Signature object.
     *
     * @exception NoSuchAlgorithmException if the algorithm is
     * not available in the environment.
     */
    public static Signature getInstance(String algorithm) 
    throws NoSuchAlgorithmException {
	try {
	    return (Signature)Security.getImpl(algorithm, "Signature", null);
	} catch(NoSuchProviderException e) {
	    throw new InternalError("please send a bug report via " +
				    System.getProperty("java.vendor.url.bug"));
	}
    }

    /** 
     * 生成实现指定算法的Signature对象（由指定提供者提供）（如果提供者提供此类算法）。
     *
     * @param 算法请求的算法的名称。有关标准算法名称的信息，
     * 请参阅《<a href= "../guide/security/CryptoSpec.html#AppA">Java加密架构API规范参考》</a>中的附录A。
     *
     * @param provider the name of the provider.
     *
     * @return the new Signature object.
     *
     * @exception 如果该算法在请求的提供商提供的包中不可用，则出现NoSuchDelivermResponse异常。
     *
     * @exception NoSuchProviderException if the provider is not
     * available in the environment. 
     * 
     * @see Provider 
     */
    public static Signature getInstance(String algorithm, String provider) 
    throws NoSuchAlgorithmException, NoSuchProviderException {

	return (Signature)Security.getImpl(algorithm, "Signature", provider);
    }

    /**
     * 验证此对象以进行验证。如果使用不同的参数再次调用此方法，则会抵消此调用的效果。
     *
     * @param publicKey the public key of the identity whose signature is
     * going to be verified.
     *
     * @exception InvalidKeyException if the key is invalid.
     */
    public final void initVerify(PublicKey publicKey) 
    throws InvalidKeyException {
	engineInitVerify(publicKey);
	state = VERIFY;
    }

    /**
     * 初始化此对象以进行签名。如果使用不同的参数再次调用此方法，则会抵消此调用的效果。
     *
     * @param privateKey the private key of the identity whose signature
     * is going to be generated.
     * 
     * @exception InvalidKeyException if the key is invalid.  
     */
    public final void initSign(PrivateKey privateKey) 
    throws InvalidKeyException {
	engineInitSign(privateKey);
	state = SIGN;
    }

    /**
     * 返回所有更新数据的签名字节。  返回的签名是X.509编码的。
     * 
     * <p>对此方法的调用会将此签名对象重置为之前通过<code>调用initSign（PrivateKey）</code>初始化签名时的状态。
     * 也就是说，如果需要，该对象被重置并可通过新的更新和<code>签名调用</code>从同一签名者生成另一个签名。<code></code>
     *
     * @return the signature bytes of the signing operation's result.
     *
     * @exception SignatureException if this signature object is not
     * initialized properly.
     */
    public final byte[] sign() throws SignatureException {
	if (state == SIGN) {
	    return engineSign();
	}
	throw new SignatureException("object not initialized for " +
				     "signing.");
    }

    /**
     * 验证传递的签名。签名字节预计为X.509编码。
     * 
     * <p>对此方法的调用会将此签名对象重置为之前通过<code>调用initVerify（PublicKey）</code>初始化验证时的状态。
     * 也就是说，该对象被重置并可用于验证来自其公钥在<code>对initVerify</code>的调用中指定的身份的另一个签名。
     *      
     * @param signature the signature bytes to be verified.
     *
     * @return true if the signature was verified, false if not. 
     *
     * @exception SignatureException 如果此签名对象未正确初始化，或者传递的签名编码不当或类型错误等。
     */
    public final boolean verify(byte[] signature) 
	    throws SignatureException {
	if (state == VERIFY) {
	    return engineVerify(signature);
	}
	throw new SignatureException("object not initialized for " +
				     "verification.");
    }

    /**
     * Updates the data to be signed or verified by a byte.
     *
     * @param b the byte to use for the update.
     * 
     * @exception SignatureException if this signature object is not 
     * initialized properly.     
     */
    public final void update(byte b) throws SignatureException {
	if (state == VERIFY || state == SIGN) {
	    engineUpdate(b);
	} else {
	    throw new SignatureException("object not initialized for signature " +
					 "or verification.");
	}
    }

    /**
     * Updates the data to be signed or verified, using the specified
     * array of bytes.
     *
     * @param data the byte array to use for the update.       
     * 
     * @exception SignatureException if this signature object is not 
     * initialized properly.          
     */
    public final void update(byte[] data) throws SignatureException {
	update(data, 0, data.length);
    }

    /**
     * 使用指定的字节数组，从指定的偏置量开始更新要签名或验证的数据。
     *
     * @param data the array of bytes.  
     * @param off the offset to start from in the array of bytes.  
     * @param len the number of bytes to use, starting at offset.
     *  
     * @exception SignatureException if this signature object is not 
     * initialized properly.          
     */
    public final void update(byte[] data, int off, int len) 
    throws SignatureException {
	if (state == SIGN || state == VERIFY) {
	    engineUpdate(data, off, len);
	} else {
	    throw new SignatureException("object not initialized for signature " +
					 "or verification.");
	}
    }

    /** 
     * Returns the name of the algorithm for this signature object.
     * 
     * @return the name of the algorithm for this signature object.
     */
    public final String getAlgorithm() {
	return algorithm;
    }

    /**
     * 返回此签名对象的字符串表示形式，提供包括对象状态和使用的算法名称的信息。
     * 
     * @return a string representation of this signature object.
     */
    public String toString() {
	String initState = "";
	switch (state) {
	case UNINITIALIZED:
	    initState = "<not initialized>";
	    break;
	  case VERIFY:
	    initState = "<initialized for verifying>";
	    break;	      
	  case SIGN:
	    initState = "<initialized for signing>";
	    break;	      
	}
	return "Signature object: " + getAlgorithm() + initState;
    }

    /**
     * 将指定的算法参数设置为指定值。该方法提供了一种通用机制，通过该机制可以设置该对象的各种参数。
     * 参数可以是算法的任何可设置参数，例如参数大小，或签名生成的随机位的来源（如果合适的话），
     * 或是否执行特定但可选的计算的指示。每个参数需要统一的特定于算法的命名方案，但目前未指定。
     *
     * @param param the string identifier of the parameter.
     * @param value the parameter value.
     *
     * @exception InvalidParameterException
     * 如果<code>param</code>对于该签名算法引擎来说是无效的参数，则该参数已经设置并且无法再次设置，发生安全异常，等等。
     */
    public final void setParameter(String param, Object value) 
	throws InvalidParameterException {
	engineSetParameter(param, value);
    }

    /**
     * 获取指定算法参数的值。该方法提供了一种通用机制，通过该机制可以获取该对象的各种参数。
     * 参数可以是算法的任何可设置参数，例如参数大小，或签名生成的随机位的来源（如果合适的话），
     * 或是否执行特定但可选的计算的指示。每个参数需要统一的特定于算法的命名方案，但目前未指定。
     *
     * @param param the string name of the parameter.
     *
     * @return 表示参数值的对象，如果没有，则为空。
     *
     * @exception InvalidParameterException 如果<code>参数</code>对于此引擎来说是无效的参数，或者在尝试获取此参数时发生其他异常。
     */
    public final Object getParameter(String param) 
	throws InvalidParameterException {
	    return engineGetParameter(param);
    }

    /**
     * <b>SPI</b>：使用指定的公钥验证此签名对象以进行验证操作。
     *
     * @param publicKey要验证其签名的身份的公钥。
     * 
    .0
     * @exception 如果密钥编码不当、参数丢失等，则会出现InvalidKeyResponse异常
     */
    protected abstract void engineInitVerify(PublicKey publicKey)
    throws InvalidKeyException;

    /**
     * <b>SPI</b>：使用指定的私有密钥验证此签名对象以进行签名操作。
     *
     * @param privateKey将生成签名的身份的私有密钥。
     *
     * @exception 如果密钥编码不当、参数丢失等，则会出现InvalidKeyResponse。
     */
    protected abstract void engineInitSign(PrivateKey privateKey)
    throws InvalidKeyException;

   /**
     * <b>SPI</b>：使用指定字节更新要签名或验证的数据。
     *
     * @param b the byte to use for the update.
     *
     * @exception SignatureException if the engine is not initialized
     * properly.
     */
    protected abstract void engineUpdate(byte b) throws SignatureException;

    /**
     * <b>SPI</b>：使用更新要签名或验证的数据   指定的字节数组，从指定的位移开始。
     *
     * @param data the array of bytes.  
     * @param off the offset to start from in the array of bytes.  
     * @param len the number of bytes to use, starting at offset.
     *
     * @exception SignatureException if the engine is not initialized 
     * properly.
     */
    protected abstract void engineUpdate(byte[] b, int off, int len) 
        throws SignatureException;

    /** 
     * <b>SPI</b>：返回迄今为止更新的所有数据的签名字节。返回的签名是X.509编码的。
     * 有关X.509编码的更多信息，请参阅<a href = "../guide/security/cert2.html">X.509证书</a>。
     *
     * @return the signature bytes of the signing operation's result.
     *
     * @exception SignatureException if the engine is not
     * initialized properly.  
     */
    protected abstract byte[] engineSign() throws SignatureException;

    /** 
     * <b>SPI</b>：验证传递的签名。签名字节预计为X.509编码。
     * 有关X.509编码的更多信息，请参阅<a href = "../guide/security/cert2.html">X.509证书</a>。
     * 
     * @param sigBytes the signature bytes to be verified.
     *
     * @return true if the signature was verified, false if not. 
     *
     * @exception 如果引擎未正确初始化，或者传递的签名编码不当或类型错误等，则SignatureExcellent。
     */
    protected abstract boolean engineVerify(byte[] sigBytes) 
	throws SignatureException;

    /**
     * <b>SPI</b>：将指定的算法参数设置为指定值。该方法提供了一种通用机制，通过该机制可以设置该对象的各种参数。
     * 参数可以是算法的任何可设置参数，例如参数大小，或签名生成的随机位的来源（如果合适的话），或是否执行特定但可选的计算的指示。
     * 每个参数需要统一的特定于算法的命名方案，但目前未指定。
     *
     * @param param the string identifier of the parameter.
     *
     * @param value the parameter value.
     *
     * @exception InvalidDataberResponse如果<code>param</code>是该签名算法引擎的无效参数，
     * 则该参数已设置并且无法再次设置，发生安全异常，等等。
     */
    protected abstract void engineSetParameter(String param, Object value) 
	throws InvalidParameterException;

    /**
     * <b>SPI</b>：获取指定算法参数的值。该方法提供了一种通用机制，通过该机制可以获取该对象的各种参数。
     * 参数可以是算法的任何可设置参数，例如参数大小，或签名生成的随机位的来源（如果合适的话），
     * 或是否执行特定但可选的计算的指示。每个参数需要统一的特定于算法的命名方案，但目前未指定。
     *
     * @param param the string name of the parameter.
     *
     * @return the object that represents the parameter value, or null if
     * there is none.
     *
     * @exception 如果<code>param</code>是此引擎的无效参数，或者在尝试获取此参数时发生其他异常，则InvalidMechanerResponse异常。
     */
    protected abstract Object engineGetParameter(String param)
	throws InvalidParameterException;

    /**
     * Returns a clone if the implementation is cloneable.
     * 
     * @return a clone if the implementation is cloneable.
     *
     * @exception CloneNotSupportedException if this is called
     * on an implementation that does not support <code>Cloneable</code>.
     */
    public Object clone() throws CloneNotSupportedException {
	if (this instanceof Cloneable) {
	    return super.clone();
	} else {
	    throw new CloneNotSupportedException();
	}
    }

    // private debugging method.
    private static void debug(String statement) {
	if (debug) {
	    System.err.println(statement);
	}
    }

    // private debugging method.
    private static void debug(Exception e) {
	if (debug) {
	    e.printStackTrace();
	}
    }

}
    
	    



	    
	    
	
